/* 
   main.c
   By:
   Date created:
   Date modified: April 2nd 2011
   Modified By: Erin Szilagyi
                Samuel Ferguson

   main.c - This is where the main setup of the kernel will be done.  This 
   is all done in protected mode.  It includes initializing hardware,
   interrupts, multitasking, and our spawning off our first processe(s).
*/

#include <memory.h>
#include <init.h>
#include <interrupt.h>
#include <keyboard.h>
#include <clock.h>
#include <xxxio.h>
#include <proc.h>
#include <syscalls.h>
#include <definitions.h>

extern void init_proc(void); /* defined in proc_init.S */
extern void kernel_panic(void); /* defined in int_handler.S */

int semaphore = 1;
long sleep = 1000000000;

/* process A */
void processA()
{
  int i,j=4;
  sleep *= 50;
  while(1){
    for(i=0;i<sleep;i++){
      j = j * i;
    }
    xprintf("Semaphore = %i\n", semaphore);
    if (semaphore == 0){
      semaphore = 1;
      xprintf("PROCESS AAAA IS IN CONTROL NOW!!!!!!!!!!!!\n");
    }
  }
}

/* process B */
void processB()
{
  int i,j=4;  
  sleep *= 50;
  while(1){
    for(i=0;i<sleep;i++){
      j = j * i;
    }
    xprintf("Semaphore = %i\n", semaphore);
    if (semaphore == 1){
      semaphore = 0;
      xprintf("PROCESS BBBB IS IN CONTROL NOW!!!!!!!!!!!!\n");
    }
  }
}

void spin()
{
  xprintf("spinning\n");
 spin:
  goto spin;
}

void k_main()
{
  struct task_struct a,b,idle;
  
  pid_t result;

  xxxio_init(); /* No idea what this does. */
  xprintf_c(char_colour(RED,BLACK), " Welcome to XXXOS!\n\n");

  /* Memory-Init */
  init_mem();

  init_task_queues(); /* initializes RUNNING, IDLE, and WAIT queues */
  init_proc();  /* copies the %esp to global variable current_kstack */
                /* not sure why - Sam*/

  idt_install();
  init_PIC();

  init_keyboard();

  /* setting up the idle process PCB */
  init_task(&idle, TASK_IDLE, 0, 0, allocate_process(), spin);
  /* xprintf("main.c:%i spin: %i\n",__LINE__, processA); */
  /* printTask(&idle); */
  init_task(&a, TASK_RUNNING, 10, 0, allocate_process(), processA);
  /* xprintf("main.c:%i processA: %i\n",__LINE__, processA); */
  /* printTask(&a); */
  init_task(&b, TASK_RUNNING, 20, 0, allocate_process(), processB);
  /* xprintf("main.c:%i processA: %i\n",__LINE__, processB); */
  /* printTask(&b);  */

  /* xprintf("task a's address: %i\n", &a); */
  /* xprintf("process a esp %i\n", a->esp0); */
  setCurrentTask(&idle);

  xprintf("main.c:%i kernel_panic: %x\n",__LINE__, kernel_panic);

  /* printTask(&a); */
  /* printCurrEsp();*/
  /* adding idle's PCB to the running task queue */
  enqueue_task(&a);
  enqueue_task(&b);

  a.next = &b; 
  b.next = &a;
  /* result = fork(); */
  /* print_running_queue(); */  
  /* xprintf("Fork returned %x\n", result); */
  /*  spork(42);*/
  /*  xprintf("Syscalls done\n");*/
  init_clock();

  spin();
}

